/** @file    Variant.cpp
 *  @author  Alessandro Polo
 *  @version $Id: Variant.cpp 2829 2010-08-02 20:45:47Z alex $
 *  @brief
 * File containing methods for the wosh::Variant class.
 * The header for this class can be found in Variant.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/
 
 #include <core/Variant.h>
 #include <core/ObjectAllocator.h>
 #include <core/Utilities.h>


using namespace std;
namespace wosh {

 WOSH_REGISTER(wosh::Variant, "wosh::ISerializable", 1.01, _static_Variant)

const std::string EmptyString = "";		///< static optimization
const Variant Variant::EmptyVariant;	///< static optimization

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////// OPERATORS

// int memcmp ( const void * ptr1, const void * ptr2, size_t num );
// A value greater than zero indicates that the first byte that does not match in both memory blocks
// has a greater value in ptr1 than in ptr2 as if evaluated as unsigned char values;

Variant& Variant::operator=( const Variant& m ) {
	if (this == &m) return *this; // same object?

	if ( this->vType < Variant::CHARS && m.vType < Variant::CHARS ) {
		this->vType = m.vType;
		memcpy(&this->vHolder, &m.vHolder, sizeof(Variant::vHolder));
		return *this;
	 }
	// one of them is string|array

	if ( this->vType == m.vType && this->vType == Variant::STRING ) { // optimization
		if ( (this->vHolder.v_pstr == NULL) && (m.vHolder.v_pstr == NULL) )
			return *this;
		if ( m.vHolder.v_pstr == NULL ) {
			freePtrs();
			return *this;
		 }
		if ( this->vHolder.v_pstr == NULL ) {
			this->vHolder.v_pstr = new string(*m.vHolder.v_pstr);
			return *this;
		 }
		*this->vHolder.v_pstr = *m.vHolder.v_pstr;
		return *this;
	 }
	freePtrs();
	if ( m.vType == Variant::CHARS ) {
		this->vType = Variant::CHARS;
		this->vHolder.v_pchar = NULL;
		if ( m.vHolder.v_pchar == NULL )
			return *this;
		this->vHolder.v_pchar = new char[ strlen(m.vHolder.v_pchar) ];
		memcpy(this->vHolder.v_pchar, m.vHolder.v_pchar, strlen(m.vHolder.v_pchar));
		return *this;
	 }
	if ( m.vType == Variant::STRING ) {
		this->vType = Variant::STRING;
		this->vHolder.v_pstr = NULL;
		if ( m.vHolder.v_pstr == NULL )
			return *this;
		this->vHolder.v_pstr = new string(*m.vHolder.v_pstr);
		return *this;
	 }
	this->vType = Variant::EMPTY;
	return *this;
 }

bool Variant::operator==( const Variant& other ) const {
	//printf("Variant::operator== : [%s]%s ?= [%s]%s", this->getTypeAsString(true), this->toString().c_str(), other.getTypeAsString(true), other.toString().c_str() );
	if ( this->vType != other.vType ) {
		if ( this->vType >= Variant::INTEGER && this->vType <= Variant::LONG ) {
			if ( this->vType < Variant::INTEGER && this->vType > Variant::LONG )
				return false;
			else
				return ( this->vHolder.v_long == other.vHolder.v_long );
		 }
		if ( this->vType >= Variant::INT64 && this->vType <= Variant::TIMESPAN ) {
			if ( this->vType < Variant::INT64 && this->vType > Variant::TIMESPAN )
				return false;
			else
				return ( this->vHolder.v_int64 == other.vHolder.v_int64 );
		 }
		return false; // STRICT TYPE CHECK
	 }
	if ( this->vType == Variant::EMPTY )	return true;
	if ( this->vType == Variant::BOOLEAN )	return ( this->vHolder.v_bool == other.vHolder.v_bool );
	if ( this->vType == Variant::INTEGER )	return ( this->vHolder.v_bool == other.vHolder.v_bool );
	if ( this->vType == Variant::LONG )		return ( this->vHolder.v_long == other.vHolder.v_long );
	if ( this->vType == Variant::INT64 )	return ( this->vHolder.v_int64 == other.vHolder.v_int64 );
	if ( this->vType == Variant::DATETIME )	return ( this->vHolder.v_int64 == other.vHolder.v_int64 );
	if ( this->vType == Variant::TIMESPAN )	return ( this->vHolder.v_int64 == other.vHolder.v_int64 );
	if ( this->vType == Variant::DOUBLE )	return ( this->vHolder.v_double == other.vHolder.v_double );
	if ( this->vType == Variant::FLOAT )	return ( this->vHolder.v_float == other.vHolder.v_float );
	if ( this->vType == Variant::CHARS ) {
		if ( (this->vHolder.v_pchar == NULL) && (other.vHolder.v_pchar == NULL) )
			return true;
		return (strcmp(this->vHolder.v_pchar, other.vHolder.v_pchar ) == 0); // must be null terminated
	 }
	if ( this->vType == Variant::STRING ) {
		if ( (this->vHolder.v_pstr == NULL) && (other.vHolder.v_pstr == NULL) )
			return true;
		return ( *this->vHolder.v_pstr == *other.vHolder.v_pstr ); // forward to string::operator=
	 }
	return false;
 }

bool Variant::operator==( const char* other ) const {
	if ( this->vType == Variant::STRING ) {
		if ( this->vHolder.v_pstr == NULL && other == NULL )
			return true;
		if ( other == NULL )
			return false;
		return ( *this->vHolder.v_pstr == other );
	 }
	return false;
 }
bool Variant::operator==( const bool& other ) const {
	if ( isBoolean() ) return (asBoolean()==other);
	if ( isNumeric() ) return (toInteger((int)!other)==(int)other);
	return false;
 }
bool Variant::operator==( const int& other ) const {
	if ( isInteger() ) return (asInteger()==other);
	if ( isNumeric() ) return (toInteger(other+1)==other);
	return false;
 }
bool Variant::operator==( const long& other ) const {
	if ( isLong() ) return (asLong()==other);
	if ( isNumeric() ) return (toLong(other+1)==other);
	return false;
 }
bool Variant::operator==( const int64& other ) const {
	if ( isInt64() ) return (asInt64()==other);
	if ( isNumeric() ) return (toInt64(other+1)==other);
	return false;
 }

bool Variant::operator==( const std::string& other ) const {
	if (!isString()) return false;
	if ( this->vHolder.v_pstr == NULL ) return false;
	return ( *this->vHolder.v_pstr == other );
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool Variant::operator>( const Variant& other ) const {
	if ( this->vType > other.vType ) return true;
	if ( this->vType < other.vType ) return false;
	if ( this->vType == Variant::BOOLEAN )	return ( this->vHolder.v_bool > other.vHolder.v_bool );
	if ( this->vType == Variant::INTEGER )	return ( this->vHolder.v_bool > other.vHolder.v_bool );
	if ( this->vType == Variant::LONG )		return ( this->vHolder.v_long > other.vHolder.v_long );
	if ( this->vType == Variant::INT64 )	return ( this->vHolder.v_int64 > other.vHolder.v_int64 );
	if ( this->vType == Variant::DATETIME )	return ( this->vHolder.v_int64 > other.vHolder.v_int64 );
	if ( this->vType == Variant::TIMESPAN )	return ( this->vHolder.v_int64 > other.vHolder.v_int64 );
	if ( this->vType == Variant::DOUBLE )	return ( this->vHolder.v_double > other.vHolder.v_double );
	if ( this->vType == Variant::FLOAT )	return ( this->vHolder.v_float > other.vHolder.v_float );
	if ( this->vType == Variant::CHARS ) {
		if ( (this->vHolder.v_pchar == NULL) && (other.vHolder.v_pchar == NULL) ) return true;
		if ( other.vHolder.v_pchar == NULL ) return true;
		if ( this->vHolder.v_pchar == NULL ) return false;
		return (strcmp(this->vHolder.v_pchar, other.vHolder.v_pchar ) > 0); // must be null terminated
	 }
	else if ( this->vType == Variant::STRING ) {
		if ( (this->vHolder.v_pstr == NULL) && (other.vHolder.v_pstr == NULL) ) return true;
		if ( other.vHolder.v_pstr == NULL ) return true;
		if ( this->vHolder.v_pstr == NULL ) return false;
		return ( *this->vHolder.v_pstr > *other.vHolder.v_pstr ); // forward to string::operator>
	 }
	return false;
 }

bool Variant::operator<( const Variant& other ) const {
	if ( this->vType < other.vType ) return true;
	if ( this->vType > other.vType ) return false;
	if ( this->vType == Variant::BOOLEAN )	return ( this->vHolder.v_bool < other.vHolder.v_bool );
	if ( this->vType == Variant::INTEGER )	return ( this->vHolder.v_bool < other.vHolder.v_bool );
	if ( this->vType == Variant::LONG )		return ( this->vHolder.v_long < other.vHolder.v_long );
	if ( this->vType == Variant::INT64 )	return ( this->vHolder.v_int64 < other.vHolder.v_int64 );
	if ( this->vType == Variant::DATETIME )	return ( this->vHolder.v_int64 < other.vHolder.v_int64 );
	if ( this->vType == Variant::TIMESPAN )	return ( this->vHolder.v_int64 < other.vHolder.v_int64 );
	if ( this->vType == Variant::DOUBLE )	return ( this->vHolder.v_double < other.vHolder.v_double );
	if ( this->vType == Variant::FLOAT )	return ( this->vHolder.v_float < other.vHolder.v_float );
	if ( this->vType == Variant::CHARS ) {
		if ( (this->vHolder.v_pchar == NULL) && (other.vHolder.v_pchar == NULL) )
			return true;
		if ( this->vHolder.v_pchar == NULL ) return true;
		if ( other.vHolder.v_pchar == NULL ) return false;
		return (strcmp(this->vHolder.v_pchar, other.vHolder.v_pchar ) < 0); // must be null terminated
	 }
	else if ( this->vType == Variant::STRING ) {
		if ( (this->vHolder.v_pstr == NULL) && (other.vHolder.v_pstr == NULL) ) return true;
		if ( this->vHolder.v_pstr == NULL ) return true;
		if ( other.vHolder.v_pstr == NULL ) return false;
		return ( *this->vHolder.v_pstr < *other.vHolder.v_pstr ); // forward to string::operator<
	 }
	return false;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

#undef OPpType_ADD
#define OPpType_ADD(TYPE, FIELD)				\
		else if ( TYPE == this->vType )			\
			result.vHolder.FIELD = this->vHolder.FIELD + other.vHolder.FIELD;

const Variant Variant::operator+( const Variant& other ) const {
	Variant result;
	if ( this->vType != other.vType ) return result;

	if ( this->vType == Variant::STRING ) {
		result.vType = Variant::STRING;
		if ( this->vHolder.v_pstr == NULL && other.vHolder.v_pstr == NULL )
			return result;
		else if ( this->vHolder.v_pstr == NULL )
			result.set(*other.vHolder.v_pstr);
		else if ( other.vHolder.v_pstr == NULL )
			result.set(*this->vHolder.v_pstr);
		result.vHolder.v_pstr = new string(*this->vHolder.v_pstr);
		*result.vHolder.v_pstr += *other.vHolder.v_pstr;
	 }
	else if ( this->vType > Variant::CHARS ) {

		return result;
	 }
	else if ( Variant::BOOLEAN == this->vType )
		result.vHolder.v_bool = this->vHolder.v_bool | other.vHolder.v_bool;
	// else if :
	OPpType_ADD( Variant::CHAR,		v_char )
	OPpType_ADD( Variant::INTEGER,	v_long )
	OPpType_ADD( Variant::LONG,		v_long )
	OPpType_ADD( Variant::INT64,	v_int64 )
	OPpType_ADD( Variant::DATETIME,	v_int64 )
	OPpType_ADD( Variant::TIMESPAN,	v_int64 )
	OPpType_ADD( Variant::DOUBLE,	v_double )
	OPpType_ADD( Variant::FLOAT,	v_float )
	result.vType = this->vType;
	return result;
}

/////////////////////////////////////////////////////////////////////////////////////////////////// OPERATORS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////// CONVERSIONS

#undef asType_RET
#define asType_RET(type, ret)				\
		else if ( type == this->vType )		\
				return ret;

bool Variant::toBoolean( bool default_value ) const {
	if ( Variant::EMPTY == this->vType ) return default_value;
	asType_RET( Variant::BOOLEAN,	vHolder.v_bool )
	asType_RET( Variant::CHAR,		(vHolder.v_char==0) )
	asType_RET( Variant::INTEGER,	(vHolder.v_long==0L) )
	asType_RET( Variant::LONG,		(vHolder.v_long==0L) )
	asType_RET( Variant::INT64,		(vHolder.v_int64==0L) )
	asType_RET( Variant::DATETIME,	(vHolder.v_int64==0L) )
	asType_RET( Variant::TIMESPAN,	(vHolder.v_int64==0L) )
	asType_RET( Variant::DOUBLE,	(vHolder.v_double==0.0) )
	asType_RET( Variant::FLOAT,		(vHolder.v_float==0.0F) )

	else if ( Variant::STRING == this->vType ) {
		if ( this->vHolder.v_pstr == NULL )
			return default_value;
		return Utilities::fromString<bool>( *this->vHolder.v_pstr );
	 }
	else if ( Variant::CHARS == this->vType ) {
		// WOSH_DEPRECATED
	 }
	return default_value;
 }

int Variant::toInteger( int default_value ) const {
	if ( Variant::EMPTY == this->vType ) return default_value;
	asType_RET( Variant::BOOLEAN,	(int)vHolder.v_bool )
	asType_RET( Variant::CHAR,		(int)vHolder.v_char )
	asType_RET( Variant::INTEGER,	(int)vHolder.v_long )
	asType_RET( Variant::LONG,		(int)vHolder.v_long )
	asType_RET( Variant::INT64,		(int)vHolder.v_int64 )
	asType_RET( Variant::DATETIME,	(int)vHolder.v_int64 )
	asType_RET( Variant::TIMESPAN,	(int)vHolder.v_int64 )
	asType_RET( Variant::DOUBLE,	(int)vHolder.v_double )
	asType_RET( Variant::FLOAT,		(int)vHolder.v_float )

	else if ( Variant::STRING == this->vType ) {
		if ( this->vHolder.v_pstr == NULL )
			return default_value;
		return Utilities::fromString<int>( *this->vHolder.v_pstr );
	 }
	else if ( Variant::CHARS == this->vType ) {
		// WOSH_DEPRECATED
	 }
	return default_value;
 }

long Variant::toLong( long default_value ) const {
	if ( Variant::EMPTY == this->vType ) return default_value;
	asType_RET( Variant::BOOLEAN,	(long)vHolder.v_bool )
	asType_RET( Variant::CHAR,		(long)vHolder.v_char )
	asType_RET( Variant::INTEGER,	(long)vHolder.v_long )
	asType_RET( Variant::LONG,		(long)vHolder.v_long )
	asType_RET( Variant::INT64,		(long)vHolder.v_int64 )
	asType_RET( Variant::DATETIME,	(long)vHolder.v_int64 )
	asType_RET( Variant::TIMESPAN,	(long)vHolder.v_int64 )
	asType_RET( Variant::DOUBLE,	(long)vHolder.v_double )
	asType_RET( Variant::FLOAT,		(long)vHolder.v_float )

	else if ( Variant::STRING == this->vType ) {
		if ( this->vHolder.v_pstr == NULL )
			return default_value;
		return Utilities::fromString<long>( *this->vHolder.v_pstr );
	 }
	else if ( Variant::CHARS == this->vType ) {
		// WOSH_DEPRECATED
	 }
	return default_value;
 }

int64 Variant::toInt64( int64 default_value ) const {
	if ( Variant::EMPTY == this->vType ) return default_value;
	asType_RET( Variant::BOOLEAN,	(int64)vHolder.v_bool )
	asType_RET( Variant::CHAR,		(int64)vHolder.v_char )
	asType_RET( Variant::INTEGER,	(int64)vHolder.v_long )
	asType_RET( Variant::LONG,		(int64)vHolder.v_long )
	asType_RET( Variant::INT64,		(int64)vHolder.v_int64 )
	asType_RET( Variant::DATETIME,	(int64)vHolder.v_int64 )
	asType_RET( Variant::TIMESPAN,	(int64)vHolder.v_int64 )
	asType_RET( Variant::DOUBLE,	(int64)vHolder.v_double )
	asType_RET( Variant::FLOAT,		(int64)vHolder.v_float )

	else if ( Variant::STRING == this->vType ) {
		if ( this->vHolder.v_pstr == NULL )
			return default_value;
		return Utilities::fromString<int64>( *this->vHolder.v_pstr );
	 }
	else if ( Variant::CHARS == this->vType ) {
		// WOSH_DEPRECATED
	 }
	return default_value;
 }

double Variant::toDouble( double default_value ) const {
	if ( Variant::EMPTY == this->vType ) return default_value;
	asType_RET( Variant::BOOLEAN,	(double)vHolder.v_bool )
	asType_RET( Variant::CHAR,		(double)vHolder.v_char )
	asType_RET( Variant::INTEGER,	(double)vHolder.v_long )
	asType_RET( Variant::LONG,		(double)vHolder.v_long )
	asType_RET( Variant::INT64,		(double)vHolder.v_int64 )
	asType_RET( Variant::DATETIME,	(double)vHolder.v_int64 )
	asType_RET( Variant::TIMESPAN,	(double)vHolder.v_int64 )
	asType_RET( Variant::DOUBLE,	(double)vHolder.v_double )
	asType_RET( Variant::FLOAT,		(double)vHolder.v_float )

	else if ( Variant::STRING == this->vType ) {
		if ( this->vHolder.v_pstr == NULL )
			return default_value;
		return Utilities::fromString<double>( *this->vHolder.v_pstr );
	 }
	else if ( Variant::CHARS == this->vType ) {
		// WOSH_DEPRECATED
	 }
	return default_value;
 }

float Variant::toFloat( float default_value ) const {
	if ( Variant::EMPTY == this->vType ) return default_value;
	asType_RET( Variant::BOOLEAN,	(float)vHolder.v_bool )
	asType_RET( Variant::CHAR,		(float)vHolder.v_char )
	asType_RET( Variant::INTEGER,	(float)vHolder.v_long )
	asType_RET( Variant::LONG,		(float)vHolder.v_long )
	asType_RET( Variant::INT64,		(float)vHolder.v_int64 )
	asType_RET( Variant::DATETIME,	(float)vHolder.v_int64 )
	asType_RET( Variant::TIMESPAN,	(float)vHolder.v_int64 )
	asType_RET( Variant::DOUBLE,	(float)vHolder.v_double )
	asType_RET( Variant::FLOAT,		(float)vHolder.v_float )

	else if ( Variant::STRING == this->vType ) {
		if ( this->vHolder.v_pstr == NULL )
			return default_value;
		return Utilities::fromString<float>( *this->vHolder.v_pstr );
	 }
	else if ( Variant::CHARS == this->vType ) {
		// WOSH_DEPRECATED
	 }
	return default_value;
 }

///////////////////////////////////////////////////////////////////////////////////////////////// CONVERSIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////// SERIALZIATION

std::string Variant::toString() const {
	if ( Variant::STRING == this->vType ) {
		if ( this->vHolder.v_pstr == NULL )
			return EmptyString;
		else
			return *this->vHolder.v_pstr; // assignment on copy
	 }
	else if ( Variant::CHARS == this->vType ) {
		if ( this->vHolder.v_pchar == NULL )
			return EmptyString;
		else
			return std::string(this->vHolder.v_pchar); // must be NULL terminated
	 }
	else if ( Variant::DATETIME == this->vType ) {
		return Utilities::getTimeStampUTF( (unsigned long)vHolder.v_int64 );
	 }
	else if ( Variant::TIMESPAN == this->vType ) {
		return Utilities::getTimeSpan( vHolder.v_int64 );
	 }
	asType_RET( Variant::BOOLEAN,	Utilities::toString(vHolder.v_bool) )
	asType_RET( Variant::CHAR,		Utilities::toString<int>((int)vHolder.v_char) )
	asType_RET( Variant::INTEGER,	Utilities::toString<long>(vHolder.v_long) )
	asType_RET( Variant::LONG,		Utilities::toString<long>(vHolder.v_long) )
	asType_RET( Variant::DOUBLE,	Utilities::toString<double>(vHolder.v_double) )
	asType_RET( Variant::FLOAT,		Utilities::toString<float>(vHolder.v_float) )

	asType_RET( Variant::INT64,		Utilities::toString<int64>(vHolder.v_int64) )

	return EmptyString;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define _Variant_Convert(VTYPE, TYPE, FIELD)	\
	else if ( type_tip == Variant::VTYPE )		\
		valid = Utilities::fromString<TYPE>(this->vHolder.FIELD, data);

Variant::DATA_TYPE Variant::fromString( const std::string& data, Variant::DATA_TYPE type_tip ) {
	clear();
	bool valid = false;
	if ( type_tip == Variant::EMPTY ) { // autodetect
		if ( data.empty() ) {
			set(data);
			return Variant::STRING;
		 }
		if ( data.size() > 4 && data.at(3) == '(' && data.at(data.size()-1) == ')' ) {
			// autodetect, input format is TYPE(value)
			std::string dType = data.substr(0,3);
			this->vType = getTypeFromString(dType.c_str(), 2);
			if ( this->vType == Variant::EMPTY )
				return Variant::EMPTY;
			else if ( data.size() > 5 ) {
				return fromString( data.substr(4, data.size()-5), this->vType );
			 }
			return this->vType;
		 }
		if ( Utilities::isBoolean(data, this->vHolder.v_bool) ) {
			this->vType = Variant::BOOLEAN;
			return Variant::BOOLEAN;
		 }
		short numeric = Utilities::isNumeric( data.c_str() );
		if ( numeric == 1 )
			return fromString( data, Variant::LONG );
		else if ( numeric == 2 )
			return fromString( data, Variant::DOUBLE );
		// else, by default we consider it a string
		return fromString( data, Variant::STRING );
	 }
	else if ( type_tip == Variant::STRING ) {
		set(data);
		valid = true;
	 }
	else if ( type_tip == Variant::CHARS ) {
		// BUG BUG BUG
		valid= false;
	 }
	else if ( type_tip == Variant::DATETIME ) {
		if ( Utilities::isNumeric(data.c_str()) )
			valid = Utilities::fromString<int64>(this->vHolder.v_int64, data);
		else {
			this->vHolder.v_int64 = (int64)Utilities::parseTimeStampUTF(data);
			valid = true;
		 }
	 }
	else if ( type_tip == Variant::TIMESPAN ) {
		if ( Utilities::isNumeric(data.c_str()) )
			valid = Utilities::fromString<int64>(this->vHolder.v_int64, data);
		else {
			vHolder.v_int64 = Utilities::parseTimeSpan(data);
			valid = true;
		 }
	 }
	else if ( type_tip == Variant::BOOLEAN ) // else would use the template method?
		valid = Utilities::fromString(this->vHolder.v_bool, data);

	_Variant_Convert(CHAR,		char,	v_char)
	_Variant_Convert(INTEGER,	long,	v_long)
	_Variant_Convert(LONG,		long,	v_long)
	_Variant_Convert(INT64,		int64,	v_int64) // bug?
	_Variant_Convert(DOUBLE,	double,	v_double)
	_Variant_Convert(FLOAT,		float,	v_float)

	if ( !valid && type_tip == Variant::EMPTY ) {
		clear();
		return Variant::EMPTY;
	 }
	this->vType = type_tip;
	if ( !valid )
		return Variant::EMPTY;
	return this->vType;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool Variant::updateHash( DataHashContext* hash_context ) const {
	if ( hash_context == NULL ) return false;
	return hash_context->update( toString() );
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////// STATIC MEMEBERS


#define _ENUM_Variant_CmpStr(typestr, nsel, name1, name2, type) {						\
	if ( nsel == 1 && strcmp(typestr, name1) == 0 ) return type;						\
	if ( nsel == 2 && strcmp(typestr, name2) == 0 ) return type;						\
	if ( nsel == 0 && (strcmp(typestr, name1) == 0 || strcmp(typestr, name2) == 0) )	\
		return type;																	\
	 }; 

Variant::DATA_TYPE Variant::getTypeFromString( const char* type, short short_name ) {
	if ( type == NULL ) return Variant::EMPTY;
	_ENUM_Variant_CmpStr(type, short_name, "boolean",	"BOL", Variant::BOOLEAN)
	_ENUM_Variant_CmpStr(type, short_name, "char",		"CHR", Variant::CHAR)
	_ENUM_Variant_CmpStr(type, short_name, "integer",	"INT", Variant::INTEGER)
	_ENUM_Variant_CmpStr(type, short_name, "long",		"LNG", Variant::LONG)
	_ENUM_Variant_CmpStr(type, short_name, "int64",		"I64", Variant::INT64)
	_ENUM_Variant_CmpStr(type, short_name, "datetime",	"DTM", Variant::DATETIME)
	_ENUM_Variant_CmpStr(type, short_name, "timespan",	"TMS", Variant::TIMESPAN)
	_ENUM_Variant_CmpStr(type, short_name, "double",	"DBL", Variant::DOUBLE)
	_ENUM_Variant_CmpStr(type, short_name, "float",		"FLO", Variant::FLOAT)
	_ENUM_Variant_CmpStr(type, short_name, "chars",		"CAR", Variant::CHARS)
	_ENUM_Variant_CmpStr(type, short_name, "string",	"STR", Variant::STRING)
	return Variant::EMPTY;
 }


#define _ENUM_Variant_CmpType(typed, short_name, name1, name2, type) {	\
	if ( typed == type ) {												\
		if ( short_name ) return name2;									\
		return name1;													\
	 } };

const char* Variant::getTypeAsString( Variant::DATA_TYPE type, bool short_name ) {
	_ENUM_Variant_CmpType(type, short_name, "empty",	"EMP", Variant::EMPTY)
	_ENUM_Variant_CmpType(type, short_name, "boolean",	"BOL", Variant::BOOLEAN)
	_ENUM_Variant_CmpType(type, short_name, "char",		"CHR", Variant::CHAR)
	_ENUM_Variant_CmpType(type, short_name, "integer",	"INT", Variant::INTEGER)
	_ENUM_Variant_CmpType(type, short_name, "long",		"LNG", Variant::LONG)
	_ENUM_Variant_CmpType(type, short_name, "int64",	"I64", Variant::INT64)
	_ENUM_Variant_CmpType(type, short_name, "datetime",	"DTM", Variant::DATETIME)
	_ENUM_Variant_CmpType(type, short_name, "timespan",	"TMS", Variant::TIMESPAN)
	_ENUM_Variant_CmpType(type, short_name, "double",	"DBL", Variant::DOUBLE)
	_ENUM_Variant_CmpType(type, short_name, "float",	"FLO", Variant::FLOAT)
	_ENUM_Variant_CmpType(type, short_name, "chars",	"CAR", Variant::CHARS)
	_ENUM_Variant_CmpType(type, short_name, "string",	"STR", Variant::STRING)
	if ( short_name ) return "UNK";
	return "unknown";
 }

///////////////////////////////////////////////////////////////////////////////////////////// STATIC MEMEBERS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////////////////// SERIALZIATION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

}; // namespace wosh
